home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / cc04.arc / USQ1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-03-15  |  8.5 KB  |  380 lines

  1. /* Program to unsqueeze files formed by sq.com
  2.  *
  3.  *
  4.  *
  5.  */
  6. /* CHANGE HISTORY:
  7.  * 1.3    Close inbuff to avoid exceeding maximum number of
  8.  *    open files. Includes rearranging error exits.
  9.  * 1.4    Add -count option to allow quick inspection of files.
  10.  * 1.5  Break up long lines of introductory text
  11.  * 1.5  -count no longer appends formfeed to preview of each file.
  12.  *    -fcount (-f10, -F10) does append formfeed.
  13.  * 2.0  hacked for MSDOS, removed manual input, added usage print.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <ctype.h>
  18.  
  19. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  20. #define DLE 0x90        /* *** Stuff for first translation module *** */
  21. #define SPEOF 256        /* special endfile token */
  22. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  23. #define LARGE 30000
  24. #define ERROR -1
  25.  
  26. unsigned crc;            /* error check code */
  27. char outdrv[3];            /* current output drive (string) */
  28.  
  29. struct {            /* Decoding tree */
  30.     int children[2];    /* left, right */
  31. } dnode[NUMVALS - 1];
  32.  
  33. int bpos;            /* last bit position read */
  34. int curin;            /* last byte value read */
  35. int repct;            /*Number of times to retirn value*/
  36. int value;            /*current byte value or EOF */
  37. char origname[14];        /* Original file name without drive */
  38.  
  39. #define VERSION "2.0   17 Jan. 83"
  40.  
  41.                 /* This must follow all include files */
  42. unsigned dispcnt;        /* How much of each file to preview */
  43. char    ffflag;            /* should formfeed separate preview from 
  44.                    different files */
  45.  
  46. main(argc, argv)
  47. int argc;
  48. char *argv[];
  49. {
  50. int i,c;
  51. char inparg[16];        /* parameter from input */
  52.  
  53.     dispcnt = 0;        /* Not in preview mode */
  54.  
  55.     printf("File unsqueezer version 2.00 by Richard Greenlaw\n");
  56.     printf("251 Colony Ct. Gahanna OH 43230\n");
  57.  
  58.     /* Initialize output drive to default drive */
  59.     outdrv[0]  = '\0';
  60.     /* But prepare for a specific drive */
  61.     outdrv[1] = ':';
  62.     outdrv[2] = '\0';    /* string terminator */
  63.  
  64.     /* Process the parameters in order */
  65.     for(i = 1; i < argc; ++i)
  66.         obey(argv[i]);
  67.  
  68.     if(argc < 2) {
  69.         printf(" Useage:\n");
  70.         printf("    USQ item ...\n");
  71.         printf(" where ... represents more (optional) items and\n");
  72.         printf(" 'item' is either:\n");
  73.         printf("    drive:        to change the output drive\n");
  74.         printf("    file        input file\n");
  75.         printf("    drive:file    input file\n");
  76.         printf("    -count        Previewing feature: redirects output\n");
  77.         printf("    -fcount        Same as -count except formfeed\n");
  78.         printf("            appended to preview of each file.\n");
  79.         printf("            Example: -f10.\n");
  80.     }
  81.     exit();
  82. }
  83.  
  84. obey(p)
  85. char *p;
  86. {
  87.     char *q;
  88.  
  89.     if(*p == '-') {
  90.         if(ffflag = (toupper(*(p+1)) == 'F'))
  91.             ++p;
  92.         /* Set number of lines of each file to view */
  93.         dispcnt = 65535;    /* default */
  94.         if(*(p+1)) {
  95.             if((dispcnt = atoi(p + 1)) == 0)
  96.                 printf( "BAD COUNT %s\n", p + 1);
  97.         } 
  98.         return;
  99.     }    
  100.  
  101.     if(*(p + 1) == ':') {
  102.         /* Got a drive */
  103.         if(isalpha(*p)) {
  104.             if(*(p+2) == '\0') {
  105.                 /* Change output drive */
  106.                 dispcnt = 0;    /* cancel previewing */
  107.                 printf("Output drive =%s\n",p);
  108.                 outdrv[0] = *p;
  109.                 return;
  110.             }
  111.         } else {
  112.             printf( "ERROR - Ignoring %s\n", p);
  113.             return;
  114.         }
  115.     }
  116.  
  117.     /* Check for ambiguous (wild-card) name */
  118.     for(q = p; *q != '\0'; ++q)
  119.         if(*q == '*' || *q == '?') {
  120.             printf( "Can't accept ambiguous name %s\n", p);
  121.             return;
  122.         }
  123.  
  124.     unsqueeze(p);
  125. }
  126.  
  127.  
  128. unsqueeze(infile)
  129. char *infile;
  130. {
  131. int inbuff, outbuff;    /* file buffers */
  132. int i, c;
  133. char cc;
  134. int fc;
  135.  
  136.     char *p;
  137.     unsigned filecrc;    /* checksum */
  138.     int numnodes;        /* size of decoding tree */
  139.     char outfile[16];    /* output file name */
  140.     unsigned linect;    /* count of number of lines previewed */
  141.  
  142.     inbuff= open(infile,0x8000);
  143.     if (inbuff == ERROR) {
  144.         printf( "Can't find %s\n", infile);
  145.         return;
  146.     }
  147.     /* Initialization */
  148.     linect = 0;
  149.     crc = 0;
  150.     init_cr();
  151.     init_huff();
  152.  
  153.     /* Process header */
  154.     if(ugetw(inbuff) != RECOGNIZE) {
  155.         printf( "%s is not a squeezed file\n", infile);
  156.         goto closein;
  157.     }
  158.  
  159.     filecrc = ugetw(inbuff);
  160.  
  161.     /* Get original file name */
  162.     p = origname;    /* send it to array */
  163.     do {
  164.         *p = ugetc(inbuff);
  165.     } while(*p++ != '\0');
  166.  
  167.     /* Combine with output drive */
  168.     outfile[0] = '\0';        /* empty */
  169.     strcat(outfile, outdrv);    /* drive */
  170.     strcat(outfile, origname);    /* name */
  171.  
  172. /* Scan the name for illegal characters; replace them with a dash. */
  173.  
  174.     fc= 0;
  175.     while (outfile[fc]) {
  176.         if ((outfile[fc] == '/') || (outfile[fc] == '\\')) {
  177.             printf("Illegal character in filename: ");
  178.             printf("'%c' changed to '$'\n",outfile[fc]);
  179.             outfile[fc]= '$';
  180.         }
  181.         ++fc;
  182.     }
  183.     printf("%s -> %s: \n", infile, outfile);
  184.  
  185.  
  186.     numnodes = ugetw(inbuff);
  187.  
  188.     if(numnodes < 0 || numnodes >= NUMVALS) {
  189.         printf( "%s has invalid decode tree size\n", infile);
  190.         goto closein;
  191.     }
  192.  
  193.     /* Initialize for possible empty tree (SPEOF only) */
  194.     dnode[0].children[0] = -(SPEOF + 1);
  195.     dnode[0].children[1] = -(SPEOF + 1);
  196.  
  197.     /* Get decoding tree from file */
  198.     for(i = 0; i < numnodes; ++i) {
  199.         dnode[i].children[0] = ugetw(inbuff);
  200.         dnode[i].children[1] = ugetw(inbuff);
  201.     }
  202.  
  203.     if(dispcnt) {
  204.         /* Use standard output for previewing */
  205.         putchar('\n');
  206.         while(((c = ugetcr(inbuff)) != EOF) && (linect < dispcnt)) {
  207.             cc = 0x7f & c;    /* strip parity */
  208.             if((cc < ' ') || (cc > '~'))
  209.                 /* Unprintable */
  210.                 switch(cc) {
  211.                 case '\r':    /* return */
  212.                     /* newline will generate CR-LF */
  213.                     goto next;
  214.                 case '\n':    /* newline */
  215.                     ++linect;
  216.                 case '\f':    /* formfeed */
  217.                 case '\t':    /* tab */
  218.                     break;
  219.                 default:
  220.                     cc = '.';
  221.                 }
  222.             putchar(cc);
  223.         next: ;
  224.         }
  225.         if(ffflag)
  226.             putchar('\f');    /* formfeed */
  227.     } else {
  228.         /* Create output file */
  229.         outbuff= creat(outfile,0x8001);
  230.         if (outbuff == ERROR) {
  231.             printf( "Can't create %s\n", outfile);
  232.             goto closeall;
  233.         }
  234.         /* Get translated output bytes and write file */
  235.         while((c = ugetcr(inbuff)) != EOF) {
  236.             crc += c;
  237.             if((uputc(c, outbuff)) == ERROR) {
  238.                 printf( "Write error in %s\n", outfile);
  239.                 goto closeall;
  240.             }
  241.         }
  242.  
  243.         if(filecrc != crc)
  244.             printf( "ERROR - checksum error in %s\n", outfile);
  245.  
  246.  
  247.     closeall:
  248.         close(outbuff);
  249.     }
  250.  
  251. closein:
  252.     close(inbuff);
  253. }
  254.  
  255. /* initialize decoding functions */
  256.  
  257. init_cr()
  258. {
  259.     repct = 0;
  260. }
  261.  
  262. init_huff()
  263. {
  264.     bpos = 99;    /* force initial read */
  265. }
  266.  
  267. /* Get bytes with decoding - this decodes repetition,
  268.  * calls getuhuff to decode file stream into byte
  269.  * level code with only repetition encoding.
  270.  *
  271.  * The code is simple passing through of bytes except
  272.  * that DLE is encoded as DLE-zero and other values
  273.  * repeated more than twice are encoded as value-DLE-count.
  274.  */
  275.  
  276. int
  277. ugetcr(ib)
  278. int ib;
  279. {
  280.     int c;
  281.  
  282.     if(repct > 0) {
  283.         /* Expanding a repeated char */
  284.         --repct;
  285.         return(value);
  286.     } else {
  287.         /* Nothing unusual */
  288.         if((c = getuhuff(ib)) != DLE) {
  289.             /* It's not the special delimiter */
  290.             value = c;
  291.             if(value == EOF)
  292.                 repct = LARGE;
  293.             return(value);
  294.         } else {
  295.             /* Special token */
  296.             if((repct = getuhuff(ib)) == 0)
  297.                 /* DLE, zero represents DLE */
  298.                 return (DLE);
  299.             else {
  300.                 /* Begin expanding repetition */
  301.                 repct -= 2;    /* 2nd time */
  302.                 return (value);
  303.             }
  304.         }
  305.     }
  306. }
  307.  
  308. /* Decode file stream into a byte level code with only
  309.  * repetition encoding remaining.
  310.  */
  311.  
  312. int
  313. getuhuff(ib)
  314. int ib;
  315. {
  316. int i;
  317. int bitval;
  318.  
  319.     /* Follow bit stream in tree to a leaf*/
  320.     i = 0;    /* Start at root of tree */
  321.     do {
  322.         if(++bpos > 7) {
  323.             if((curin = ugetc(ib)) == ERROR)
  324.                 return (ERROR);
  325.             bpos = 0;
  326.             /* move a level deeper in tree */
  327.             i = dnode[i].children[1 & curin];
  328.         } else
  329.             i = dnode[i].children[1 & (curin >>= 1)];
  330.     } while(i >= 0);
  331.  
  332.     /* Decode fake node index to original data value */
  333.     i = -(i + 1);
  334.     /* Decode special endfile token to normal EOF */
  335.     i = (i == SPEOF) ? EOF : i;
  336.     return (i);
  337. }
  338. /* Various useful things for USQ. */
  339.  
  340. char ugetc(file)
  341. int file;
  342. {
  343. char c;
  344.     read(file,&c,1);
  345.     return(c);
  346. }
  347.  
  348. int ugetw(file)
  349. int file;
  350. {
  351. char cl,ch;
  352.     cl= ugetc(file);
  353.     ch= ugetc(file);
  354.     return( (ch << 8) | cl);
  355. }
  356.  
  357. int uputc(c,file)
  358. char c;
  359. int file;
  360. {    if (write(file,&c,1) != 1)
  361.         return(ERROR);
  362.     return(0);
  363. }
  364. /* ATOI() function missing from Lattice C. From Kernighan and Richie. */
  365.  
  366. atoi(s)
  367. char s[];
  368. {
  369. int i,n;
  370.  
  371.     n= 0;
  372.     for (i= 0; s[i] >= '0' && s[i] <= '9'; ++i) 
  373.         n= 10*n + s[i]-'0';
  374.     return(n);
  375. }
  376. s[i] <= '9'; ++i) 
  377.         n= 10*n + s[i]-'0';
  378.     return(n);
  379. }
  380.